#pragma once
#include <vector>
#include <memory>
#include <string>
#include <map>
#include <set>
#include "zen_log.h"

#define ZEN_VAP_DEBUG 1
#if ZEN_VAP_DEBUG || 1
#define VAP_DEBUG_LOG(...) Zen::LogD(__VA_ARGS__)
#else
#define VAP_DEBUG_LOG(...)
#endif

#define VAP_OBJECT_DEBUG 1

namespace Zen { namespace Vap {

	class Object : public std::enable_shared_from_this<Object>
	{
	public:
		template<typename _Node>
		static std::shared_ptr<_Node> Ptr(_Node* node) {
			return std::dynamic_pointer_cast<_Node>(node->shared_from_this());
		}

		template<typename _Node>
		std::shared_ptr<_Node> dynamic_shared() {
			return std::dynamic_pointer_cast<_Node>(this->shared_from_this());
		}
	public:
		Object(std::string const & name = "Object")
		{
			m_object_name = name;
			m_object_id = s_global_object_count++;

#if ZEN_VAP_DEBUG
			VAP_DEBUG_LOG("Object@new object %04d[%s] total count %d",
						  m_object_id, m_object_name.c_str(), s_global_object_count);
#endif
#if VAP_OBJECT_DEBUG
			s_all.insert(this);
#endif

		}
		virtual ~Object() {
			--s_global_object_count;
#if ZEN_VAP_DEBUG
			VAP_DEBUG_LOG("Object@delete object %04d[%s] total count %d",
						  m_object_id, m_object_name.c_str(), s_global_object_count);
#endif
#if VAP_OBJECT_DEBUG
			s_all.erase(this);
#endif
		}

		void setObjectName(std::string const & name)
		{
			m_object_name = name;
		}

		auto const & getObjectName()
		{
			return m_object_name;
		}

		int getObjectID()
		{
			return m_object_id;
		}

	protected:
		std::string m_object_name;
		int m_object_id;
		Object(Object&) = delete;
		static int s_global_object_count;
	public:
#if VAP_OBJECT_DEBUG
		static std::set<Object*> s_all;
#endif
	};
}}
